﻿using StockTradTest.Data;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace StockTradTest.strategy
{
    public partial class MyStrategy
    {
        private static string today = "";
        private static List<Stock> stocks;
        private static List<Indicator> indicatorsReal;
        //计算夏普比率，待完善
        public static string CalcSharp(List<double> funds, int startDate,int endDate)
        {
            //计算经过时间，年计
            DateTime start = IntToDateTime(startDate);
            DateTime end = IntToDateTime(endDate);
            TimeSpan past = end - start;
            double year = past.Days / 250f;
            //计算收益
            double inCome = (funds[funds.Count - 1] - funds[0]) / funds[0];
            //平均收益率
            double averageReturn = inCome / year;
            //无风险利率
            double safeReturn = 0.02;
            //回报标准差
            double  deviation = 0;
            for(int i = 1;i< funds.Count;i++)
            {
                deviation = Math.Pow(funds[i] - funds[0],2);
            }
            deviation /= funds.Count;
            double sharp = (averageReturn - safeReturn) / deviation;

            return string.Format("平均年化收益率:{0}% ,  夏普比率:{1}/n",averageReturn * 100,sharp);
        }

        public static DateTime IntToDateTime(int date)
        {
            return DateTime.ParseExact(date.ToString(), "yyyyMMdd", null);
        }
        //上市即买入，用于与策略进行对比
        public static List<double> TradBase(string code,out string record,int startDate = 0,int endDate = int.MaxValue)
        {
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync(startDate,endDate).Result;
            testTradBase.record += string.Format("开始:{0} ----结束:{1},长度:{2}\n", stocks[0].Date.ToString(), stocks[stocks.Count - 1].Date.ToString(), stocks.Count);
            List<double> funds = new List<double>();
            testTradBase.date = stocks[0].Date;
            testTradBase.BuyAtMarket(code);
            funds.Add(testTradBase.GetAllMyAsset());
            testTradBase.record += string.Format("{0}总资产:{1}\n", stocks[0].Date.ToString(), funds[0]);
            for (int i = 1; i < stocks.Count - 1; i++)
            {
                testTradBase.date = stocks[i].Date;
                funds.Add(testTradBase.GetAllMyAsset());
            }
            testTradBase.date = stocks[stocks.Count - 1].Date;
            funds.Add(testTradBase.GetAllMyAsset());
            testTradBase.record += string.Format("{0}总资产:{1}\n", stocks[stocks.Count - 1].Date.ToString(), funds[funds.Count - 1]);
            record = testTradBase.record;
            return funds;
        }
        //精简的Base
        public static double ShortBase(string code)
        {
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync().Result;
            testTradBase.date = stocks[0].Date;
            testTradBase.BuyAtMarket(code);
            testTradBase.date = stocks[stocks.Count - 1].Date;
            return testTradBase.GetAllMyAsset();
        }
        //实战测试
        public static async System.Threading.Tasks.Task TradeAberationRealAllAsync(string code, int n)
        {
            TestTradBase testTradBase = new TestTradBase();
            //不修改账户信息，直接修改realtime实时
            testTradBase.InitalMyAccountWithData(true, false);
            string oldRecord = "";
            while (true)
            {
                Thread.Sleep(1000);
                await TradeAberationRealRunAsync(code, n);
                if(oldRecord!= testTradBase.record)
                {
                    Console.Write(testTradBase.record);
                    oldRecord = testTradBase.record;
                }
            }
        }
        //实战测试
        public static async System.Threading.Tasks.Task TradeAberationRealRunAsync(string code, int n)
        {

            //判断是否已过一天，
            if (DateTime.Now.ToShortDateString() != today)
            {
                today = DateTime.Now.ToShortDateString();
                await TradeAberrationRunOnceADayAsync(code, n);
                WxPusher.HttpGet(today + code + "信息更新完成");
            }
            if (TestTradBase.CheckIfTradTime())
            {
                //RealTimeInfo realTimeInfo = GetRealTimeInfo.GetStockRealTimeInfo(code);
                //Console.WriteLine(realTimeInfo.currentPrice);
                //Console.SetCursorPosition(0, Console.CursorTop - 1);
                    
                if (TestTradBase.CheckStatus() == TradStatus.NotInSellOrBuy)
                {
                    TradeAberrationRealTimeTest(code);
                }
            }
        }
        //每日数据更新
        public static async System.Threading.Tasks.Task TradeAberrationRunOnceADayAsync(string code, int n)
        {
            if(TestTradBase.realTime)
            {
                await foreach (string str in GetStockHistory.UpdateDayAsync(code))
                {
                }
            }
            Base.CurrentCode = code;
            stocks = Base.StockDatabase.GetStockAsync().Result;
            indicatorsReal = Base.IndicatorDatabase.GetIndicatorAsync().Result;
            CalcIndicator.CalcBoll(n, stocks, ref indicatorsReal);
           

        }
        public static void TradeAberrationRealTimeTest(string code)
        {
            TestTradBase testTradBase = new TestTradBase();
            RealTimeInfo realTimeInfo = GetRealTimeInfo.GetStockRealTimeInfo(code);
            if(realTimeInfo==null || indicatorsReal == null)
            {
                WxPusher.HttpGet(code + "未获取到实时数据");
                Thread.Sleep(3600*1000*24);
                return;
            }
            if (realTimeInfo.sell1Price > indicatorsReal[indicatorsReal.Count - 1].BollUp)
            {
                testTradBase.BuyAtMarket(code);
                WxPusher.HttpGet(code + "实时价格" + realTimeInfo.sell1Price + "突破" + indicatorsReal[indicatorsReal.Count - 1].BollUp + "布林上轨，建议买入");
                Thread.Sleep(3600 * 1000 * 12);
            }
            else if (realTimeInfo.buy1Price < indicatorsReal[indicatorsReal.Count - 1].BollMd)
            {
                
                testTradBase.SellAtMarket(code);
                WxPusher.HttpGet(code + "实时价格" + realTimeInfo.buy1Price + "跌破" + indicatorsReal[indicatorsReal.Count - 1].BollMd + "布林中轨，建议卖出");
                Thread.Sleep(3600 * 1000 * 12);
            }
        }
        //结论1：均线系统似乎没啥鸟用，基本跑不赢股价涨幅
        //结论2：boll线回中策略不好用，也跑不赢股价，更加激进的5日boll线突破策略更好用
        //历史测试,n = 5 时取得最大值,但此策略为当日策略，不太稳定，放弃吧
        public static List<double> TradeAberrationTestOld(string code, int n)
        {
            TestTradBase testTradBase = new TestTradBase();
            bool haveStock = false;
            testTradBase.InitalMyAccount();
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync().Result;
            testTradBase.record += string.Format("开始:{0} ----结束:{1},长度:{2}\n", stocks[0].Date.ToString(), stocks[stocks.Count - 1].Date.ToString(), stocks.Count);
            indicatorsReal = Base.IndicatorDatabase.GetIndicatorAsync().Result;
            CalcIndicator.CalcBoll(n, stocks,ref indicatorsReal);
            if (indicatorsReal == null) return null;
            if (stocks.Count != indicatorsReal.Count)
            {
                Console.WriteLine("Count Error:{0} !={1}", stocks.Count, indicatorsReal.Count);
                return null;

            }
            if (stocks[0].Date != indicatorsReal[0].Date)
            {
                Console.WriteLine("{0} != {1}.", stocks[0].Date, indicatorsReal[0].Date);
                return null;
            }
            List<double> funds = new List<double>();
            for (int i = 0; i < stocks.Count; i++)
            {
                testTradBase.date = stocks[i].Date;
                if (i < n)
                {
                    funds.Add(testTradBase.GetAllMyAsset());
                    continue;
                }
                //只要进了这个逻辑，就不会卖出，不管是否有股票，这样交易周期更长，存在上下两种情况同时出现的只有5日线，因为太短了
                if (stocks[i].HighPrice > indicatorsReal[i].BollUp)
                {
                    //注意只要一次买入成功，则有了股票，至于后面是否买入成功无所谓
                    if (!haveStock)
                    haveStock= testTradBase.BuyAtMarket(code);
                }
                else if (stocks[i].LowPrice < indicatorsReal[i].BollMd & haveStock)
                {
                    haveStock = !testTradBase.SellAtMarket(code);

                }
                funds.Add(testTradBase.GetAllMyAsset());
            }
            return funds;
        }
        //优化过的标准Aberration测试
        public static List<double> TradeAberrationTest(string code, int n, out List<int> buyOrSell, bool isRecord = false, int startDate = 0, int endDate = int.MaxValue)
        {
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            DateTime st, ed;
            st = DateTime.Now;
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync(startDate, endDate).Result;
            ed = DateTime.Now;
            var span = ed - st;
            Console.WriteLine(span.TotalMilliseconds.ToString() + "ms");
            TestTradBase.isRecord = isRecord;
            if (isRecord) testTradBase.record += string.Format("开始:{0} ----结束:{1},长度:{2}\n", stocks[0].Date.ToString(), stocks[stocks.Count - 1].Date.ToString(), stocks.Count);
            indicatorsReal = Base.IndicatorDatabase.GetIndicatorAsync().Result;
            CalcIndicator.CalcBoll(n, stocks, ref indicatorsReal);
            buyOrSell = new List<int>();
            if (stocks[0].Date != indicatorsReal[0].Date)
            {
                Console.WriteLine("{0} != {1}.", stocks[0].Date, indicatorsReal[0].Date);
                return null;
            }
            bool inBuyStatus = true;
            List<double> funds = new List<double>();
            for (int i = 0; i < stocks.Count; i++)
            {
                testTradBase.date = stocks[i].Date;
                if (i < n)
                {
                    funds.Add(testTradBase.GetAllMyAsset());
                    buyOrSell.Add(0);
                    continue;
                }
                //如果在买入过程中
                if (inBuyStatus)
                {
                    //突破高线就买，实际运行时候为当前价
                    if (stocks[i].HighPrice > indicatorsReal[i - 1].BollUp)
                    {
                        double buyPrice = Math.Max(stocks[i].OpenPrice, indicatorsReal[i - 1].BollUp);
                        testTradBase.record += "买入价 " + buyPrice + " 收盘 " + stocks[i].ClosePrice;
                        inBuyStatus = !testTradBase.BuyAtPrice(code, buyPrice);
                        buyOrSell.Add(1);
                    }
                    else
                    {
                        buyOrSell.Add(0);
                    }
                }
                else
                {
                    //跌破中线就卖
                    if (stocks[i].LowPrice < indicatorsReal[i - 1].BollMd)
                    {
                        double sellPrice = Math.Min(stocks[i].OpenPrice, indicatorsReal[i - 1].BollMd);
                        inBuyStatus = testTradBase.SellAtPrice(code, sellPrice);
                        testTradBase.record += "卖出价 " + sellPrice + " 收盘 " + stocks[i].ClosePrice;
                        buyOrSell.Add(-1);
                    }
                    else
                    {
                        buyOrSell.Add(0);
                    }
                }


                funds.Add(testTradBase.GetAllMyAsset());
            }
            if (isRecord)
            {
                testTradBase.record += CalcSharp(funds, stocks[0].Date, stocks[stocks.Count - 1].Date);
                testTradBase.record += string.Format("{0} 总资产 {1}\n", stocks[stocks.Count - 1].Date, funds[funds.Count - 1]);
            }
            Console.Write(testTradBase.record);
            return funds;
        }

        //优化卖出时间测试
        public List<double> TradeMiddleTest(string code, int n, out List<int> buyOrSell,out string record,bool isRecord = false, int startDate = 0, int endDate = int.MaxValue)
        {
            record = "";
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            DateTime st, ed;
            st = DateTime.Now;
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync(startDate, endDate).Result;
            ed = DateTime.Now;
            var span = ed - st;
            //Console.WriteLine(span.TotalMilliseconds.ToString() + "ms");
            TestTradBase.isRecord = isRecord;
            if (isRecord) testTradBase.record += string.Format("开始:{0} ----结束:{1},长度:{2}\n", stocks[0].Date.ToString(), stocks[stocks.Count - 1].Date.ToString(), stocks.Count);
            List<Indicator> indicator = null;
            CalcIndicator.CalcBoll(n, stocks, ref indicator);
            buyOrSell = new List<int>();
            if (stocks[0].Date != indicator[0].Date)
            {
                Console.WriteLine("{0} != {1}.", stocks[0].Date, indicator[0].Date);
                return null;
            }
            bool inBuyStatus = true;
            List<double> funds = new List<double>();
            int lowday = 0;
            double lastSellPrice = 0;
            for (int i = 0; i < stocks.Count; i++)
            {
                testTradBase.date = stocks[i].Date;
                if (i < n)
                {
                    funds.Add(testTradBase.GetAllMyAsset());
                    buyOrSell.Add(0);
                    continue;
                }
                //如果在买入过程中
                if (inBuyStatus)
                {
                    //突破高线就买，实际运行时候为当前价
                    if (stocks[i].HighPrice > indicator[i - 1].BollUp)
                    {
                        lowday = 0;
                        double buyPrice = Math.Max(stocks[i].OpenPrice, indicator[i - 1].BollUp);
                        inBuyStatus = !testTradBase.BuyAtPrice(code, buyPrice);
                        buyOrSell.Add(1);

                    }
                    else
                    {
                        buyOrSell.Add(0);
                    }
                }
                else
                {
                    if (stocks[i].HighPrice > indicator[i - 1].BollUp)
                    {
                        lowday = 0;
                    }
                    //跌破中线就卖
                    if (stocks[i].LowPrice < indicator[i - 1].BollMd)
                    {
                        if (stocks[i - 1].ClosePrice < stocks[i - 2].ClosePrice)
                        {
                            lowday++;

                        }
                        if (lowday >= 2)
                        {
                            lastSellPrice = Math.Min(stocks[i].OpenPrice, indicator[i - 1].BollMd);
                            inBuyStatus = testTradBase.SellAtPrice(code, lastSellPrice);
                            buyOrSell.Add(-1);
                        }
                        else
                        {
                            buyOrSell.Add(0);
                        }
                    }
                    else
                    {
                        buyOrSell.Add(0);
                    }

                }

                record = testTradBase.record;
                funds.Add(testTradBase.GetAllMyAsset());
            }
            if (isRecord)
            {
                testTradBase.record += CalcSharp(funds, stocks[0].Date, stocks[stocks.Count - 1].Date);
                testTradBase.record += string.Format("{0} 总资产 {1}\n", stocks[stocks.Count - 1].Date, funds[funds.Count - 1]);
            }
            Console.Write(testTradBase.record);
            return funds;
        }

        //短的优化卖出时间测试
        public static double TradeShortMiddleTest(string code, int n, bool isRecord = false, int startDate = 0, int endDate = int.MaxValue)
        {
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            DateTime st, ed;
            st = DateTime.Now;
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync(startDate, endDate).Result;
            ed = DateTime.Now;
            var span = ed - st;
            Console.WriteLine(span.TotalMilliseconds.ToString() + "ms");
            TestTradBase.isRecord = isRecord;
            if (isRecord) testTradBase.record += string.Format("开始:{0} ----结束:{1},长度:{2}\n", stocks[0].Date.ToString(), stocks[stocks.Count - 1].Date.ToString(), stocks.Count);
            indicatorsReal = Base.IndicatorDatabase.GetIndicatorAsync().Result;
            CalcIndicator.CalcBoll(n, stocks, ref indicatorsReal);
            if (stocks[0].Date != indicatorsReal[0].Date)
            {
                Console.WriteLine("{0} != {1}.", stocks[0].Date, indicatorsReal[0].Date);
                return 0;
            }
            bool inBuyStatus = true;
            int lowday = 0;
            double lastSellPrice = 0;
            for (int i = 0; i < stocks.Count; i++)
            {
                testTradBase.date = stocks[i].Date;
                if (i < n)
                {
                    continue;
                }
                //如果在买入过程中
                if (inBuyStatus)
                {
                    //突破高线就买，实际运行时候为当前价
                    if (stocks[i].HighPrice > indicatorsReal[i - 1].BollUp)
                    {
                        lowday = 0;
                        double buyPrice = Math.Max(stocks[i].OpenPrice, indicatorsReal[i - 1].BollUp);
                        inBuyStatus = !testTradBase.BuyAtPrice(code, buyPrice);
                    }
                }
                else
                {
                    if (stocks[i].HighPrice > indicatorsReal[i - 1].BollUp)
                    {
                        lowday = 0;
                    }
                    //跌破中线就卖
                    if (stocks[i].LowPrice < indicatorsReal[i - 1].BollMd)
                    {
                        if (stocks[i - 1].ClosePrice < stocks[i - 2].ClosePrice)
                        {
                            lowday++;

                        }
                        if (lowday >= 2)
                        {
                            lastSellPrice = Math.Min(stocks[i].OpenPrice, indicatorsReal[i - 1].BollMd);
                            inBuyStatus = testTradBase.SellAtPrice(code, lastSellPrice);
                        }
                    }

                }
            }
            return testTradBase.GetAllMyAsset();
        }


        //优化过的标准Aberration测试，增加盈亏判断
        public static List<double> TradeAberrationPlusTest(string code, int n, out List<int> buyOrSell, bool isRecord = false, int startDate = 0, int endDate = int.MaxValue)
        {
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            DateTime st, ed;
            st = DateTime.Now;
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync(startDate, endDate).Result;
            ed = DateTime.Now;
            var span = ed - st;
            Console.WriteLine(span.TotalMilliseconds.ToString() + "ms");
            TestTradBase.isRecord = isRecord;
            if (isRecord) testTradBase.record += string.Format("开始:{0} ----结束:{1},长度:{2}\n", stocks[0].Date.ToString(), stocks[stocks.Count - 1].Date.ToString(), stocks.Count);
            indicatorsReal = Base.IndicatorDatabase.GetIndicatorAsync().Result;
            CalcIndicator.CalcBoll(n, stocks, ref indicatorsReal);
            buyOrSell = new List<int>();
            if (stocks[0].Date != indicatorsReal[0].Date)
            {
                Console.WriteLine("{0} != {1}.", stocks[0].Date, indicatorsReal[0].Date);
                return null;
            }
            bool inBuyStatus = true;
            List<double> funds = new List<double>();
            double lastHigh = 0;
            bool bigLoss = false;
            int count = 0;
            for (int i = 0; i < stocks.Count; i++)
            {
                testTradBase.date = stocks[i].Date;
                if (i < n)
                {
                    funds.Add(testTradBase.GetAllMyAsset());
                    buyOrSell.Add(0);

                    continue;
                }
                if(bigLoss)
                {
                    count++;
                    if(!inBuyStatus)
                    {
                        double sellPrice = Math.Min(stocks[i].OpenPrice, indicatorsReal[i - 1].BollMd);
                        inBuyStatus = testTradBase.SellAtPrice(code, sellPrice);
                        testTradBase.record += "卖出价 " + sellPrice + " 收盘 " + stocks[i].ClosePrice;
                        buyOrSell.Add(-1);
                    }
                    else
                    {
                        buyOrSell.Add(0);
                    }
                    funds.Add(testTradBase.GetAllMyAsset());
                    if (count == 120)
                    {
                        bigLoss = false;
                        count = 0;
                    }
                    continue;
                }
                if(stocks[i].ClosePrice>lastHigh)
                {
                    lastHigh = stocks[i].ClosePrice;
                }
                else if(stocks[i].ClosePrice < lastHigh * 0.8)
                {
                    bigLoss = true;
                    buyOrSell.Add(0);
                    funds.Add(testTradBase.GetAllMyAsset());
                    lastHigh = 0;
                    continue;
                }
                //如果在买入过程中
                if (inBuyStatus)
                {
                    //突破高线就买，实际运行时候为当前价
                    if (stocks[i].HighPrice > indicatorsReal[i - 1].BollUp)
                    {
                        double buyPrice = Math.Max(stocks[i].OpenPrice, indicatorsReal[i - 1].BollUp);
                        testTradBase.record += "买入价 " + buyPrice + " 收盘 " + stocks[i].ClosePrice;
                        inBuyStatus = !testTradBase.BuyAtPrice(code, buyPrice);       
                        lastHigh = stocks[i].ClosePrice;
                        buyOrSell.Add(1);
                    }
                    else
                    {
                        buyOrSell.Add(0);
                    }
                }
                else
                {
                    //跌破中线就卖
                    if (stocks[i].LowPrice < indicatorsReal[i - 1].BollMd)
                    {
                        inBuyStatus = testTradBase.SellAtMarket(code);
                        buyOrSell.Add(-1);
                    }
                    else
                    {
                        buyOrSell.Add(0);
                    }
                }


                funds.Add(testTradBase.GetAllMyAsset());
            }
            if (isRecord)
            {
                testTradBase.record += CalcSharp(funds, stocks[0].Date, stocks[stocks.Count - 1].Date);
                testTradBase.record += string.Format("{0} 总资产 {1}\n", stocks[stocks.Count - 1].Date, funds[funds.Count - 1]);
            }
            Console.Write(testTradBase.record);
            return funds;
        }
        //优化过的标准Aberration测试,只保留最终结果
        public static double TradeShortAberrationTest(string code, int n)
        {
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync().Result;
            TestTradBase.isRecord = false;
            indicatorsReal = Base.IndicatorDatabase.GetIndicatorAsync().Result;
            CalcIndicator.CalcBoll(n, stocks, ref indicatorsReal);
            bool inBuyStatus = true;
            for (int i = 0; i < stocks.Count; i++)
            {
                testTradBase.date = stocks[i].Date;
                if (i < n)
                {
                    continue;
                }
                //如果在买入过程中
                if (inBuyStatus)
                {
                    //突破高线就买，实际运行时候为当前价
                    if (stocks[i].HighPrice > indicatorsReal[i - 1].BollUp)
                    {
                        inBuyStatus = !testTradBase.BuyAtMarket(code);
                    }
                }
                else
                {
                    //跌破中线就卖
                    if (stocks[i].LowPrice < indicatorsReal[i - 1].BollMd)
                    {
                        inBuyStatus = testTradBase.SellAtMarket(code);

                    }
                }
            }
            return testTradBase.GetAllMyAsset();
        }

        //历史测试3,多均线系统并不好用，最优成绩基本与走势相同
        public static List<double> TradeMaTest(string code,int n)
        {
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync().Result;
            testTradBase.record += string.Format("开始:{0} ----结束:{1},长度:{2}\n", stocks[0].Date.ToString(), stocks[stocks.Count - 1].Date.ToString(), stocks.Count);
            List<double> maX = Base.IndicatorDatabase.GetMa(n);
            if (maX == null) return null;
            if (stocks.Count != maX.Count)
            {
                Console.WriteLine("Count Error:{0} !={1}", stocks.Count, maX.Count);
                return null;

            }
            bool beforeLow = false;
            bool inBuyStatus = true;
            List<double> funds = new List<double>();
            double maBefore, maNow;
            for (int i = 0; i < stocks.Count; i++)
            {
                testTradBase.date = stocks[i].Date;
                if (i < n)
                {
                    funds.Add(testTradBase.GetAllMyAsset());

                    continue;
                }
                
                maBefore = maX[i - 1];
                maNow = maX[i];
                if (inBuyStatus)
                {
                    if (!beforeLow & stocks[i-1].ClosePrice < maBefore)
                    {
                        beforeLow = true;
                    }
                    if (beforeLow & stocks[i].ClosePrice > maNow)
                    {
                        inBuyStatus = !testTradBase.BuyAtMarket(code);
                        beforeLow = false;
                    }
                }
                else
                {
                    if (stocks[i].ClosePrice < maNow)
                    {
                        inBuyStatus = !testTradBase.SellAtMarket(code);
                    }

                }
                funds.Add(testTradBase.GetAllMyAsset());
            }
            return funds;
        }
        //历史测试3,多均线系统并不好用，最优成绩基本与走势相同
        public static List<double> TradeExMaTest(string code, int m, int n)
        {
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync().Result;
            testTradBase.record += string.Format("开始:{0} ----结束:{1},长度:{2}\n", stocks[0].Date.ToString(), stocks[stocks.Count - 1].Date.ToString(), stocks.Count);
            var allIndicator = Base.IndicatorDatabase.GetIndicatorAsync().Result;
            if (allIndicator == null) return null;
            if (stocks.Count != allIndicator.Count)
            {
                Console.WriteLine("Count Error:{0} !={1}", stocks.Count, allIndicator.Count);
                return null;

            }
            if (stocks[0].Date != allIndicator[0].Date)
            {
                Console.WriteLine("{0} != {1}.", stocks[0].Date, allIndicator[0].Date);
                return null;
            }
            bool beforeLow = false; bool beforeHigh = false;
            bool inBuyStatus = true;
            List<double> funds = new List<double>();
            for (int i = 0; i < stocks.Count; i++)
            {
                testTradBase.date = stocks[i].Date;
                if (i < n)
                {
                    funds.Add(testTradBase.GetAllMyAsset());

                    continue;
                }
                double ma01, ma02, ma11, ma12;
                switch (m)
                {
                    case 5: ma01 = allIndicator[i - 1].Ma5; ma11 = allIndicator[i].Ma5; break;
                    case 10: ma01 = allIndicator[i - 1].Ma10; ma11 = allIndicator[i].Ma10; break;
                    case 20: ma01 = allIndicator[i - 1].Ma20; ma11 = allIndicator[i].Ma20; break;
                    case 30: ma01 = allIndicator[i - 1].Ma30; ma11 = allIndicator[i].Ma30; break;
                    case 60: ma01 = allIndicator[i - 1].Ma60; ma11 = allIndicator[i].Ma60; break;
                    case 120: ma01 = allIndicator[i - 1].Ma120; ma11 = allIndicator[i].Ma120; break;
                    case 250: ma01 = allIndicator[i - 1].Ma250; ma11 = allIndicator[i].Ma250; break;
                    default: ma01 = 0; ma11 = 0; break;
                }
                switch (n)
                {
                    case 5: ma02 = allIndicator[i - 1].Ma5; ma12 = allIndicator[i].Ma5; break;
                    case 10: ma02 = allIndicator[i - 1].Ma10; ma12 = allIndicator[i].Ma10; break;
                    case 20: ma02 = allIndicator[i - 1].Ma20; ma12 = allIndicator[i].Ma20; break;
                    case 30: ma02 = allIndicator[i - 1].Ma30; ma12 = allIndicator[i].Ma30; break;
                    case 60: ma02 = allIndicator[i - 1].Ma60; ma12 = allIndicator[i].Ma60; break;
                    case 120: ma02 = allIndicator[i - 1].Ma120; ma12 = allIndicator[i].Ma120; break;
                    case 250: ma02 = allIndicator[i - 1].Ma250; ma12 = allIndicator[i].Ma250; break;
                    default: ma02 = 0; ma12 = 0; break;
                }
                if (inBuyStatus)
                {
                    if (!beforeLow & ma01 < ma02)
                    {
                        beforeLow = true;
                    }
                    if (beforeLow & ma11 > ma12)
                    {
                        inBuyStatus = !testTradBase.BuyAtMarket(code);
                        beforeLow = false;
                    }
                }
                else
                {
                    if (!beforeHigh & ma01 > ma02)
                    {
                        beforeHigh = true;
                    }
                    if (beforeHigh & ma11 < ma12)
                    {
                        inBuyStatus = !testTradBase.SellAtMarket(code);
                        beforeHigh = false;
                    }

                }
                funds.Add(testTradBase.GetAllMyAsset());
            }
            return funds;
        }
        #region Dual Thrust测试，已证明没有鸟用
        public static List<double> DualThrustTest(string code, int n, double k1, double k2, bool isRecord = false, int startDate = 0, int endDate = int.MaxValue)
        {
            TestTradBase testTradBase = new TestTradBase();
            testTradBase.InitalMyAccount();
            DateTime st, ed;
            st = DateTime.Now;
            Base.CurrentCode = code;
            List<Stock> stocks = Base.StockDatabase.GetStockAsync(startDate, endDate).Result;
            ed = DateTime.Now;
            var span = ed - st;
            Console.WriteLine(span.TotalMilliseconds.ToString() + "ms");
            TestTradBase.isRecord = isRecord;
            if (isRecord) testTradBase.record += string.Format("开始:{0} ----结束:{1},长度:{2}\n", stocks[0].Date.ToString(), stocks[stocks.Count - 1].Date.ToString(), stocks.Count);
            var allIndicator = CalcRange(n, k1, k2, stocks);
            if (allIndicator == null) return null;
            if (stocks.Count != allIndicator.Count)
            {
                Console.WriteLine("Count Error:{0} !={1}", stocks.Count, allIndicator.Count);
                return null;

            }
            if (stocks[0].Date != allIndicator[0].Date)
            {
                Console.WriteLine("{0} != {1}.", stocks[0].Date, allIndicator[0].Date);
                return null;
            }
            bool inBuyStatus = true;
            List<double> funds = new List<double>();
            for (int i = 0; i < stocks.Count; i++)
            {
                testTradBase.date = stocks[i].Date;
                if (i < n)
                {
                    funds.Add(testTradBase.GetAllMyAsset());
                    continue;
                }
                //如果在买入过程中
                if (inBuyStatus)
                {
                    //突破高线就买，实际运行时候为当前价
                    if (stocks[i].HighPrice > allIndicator[i - 1].BollUp)
                    {
                        inBuyStatus = !testTradBase.BuyAtMarket(code);
                    }
                }
                else
                {
                    //跌破中线就卖
                    if (stocks[i].LowPrice < allIndicator[i - 1].BollDown)
                    {
                        inBuyStatus = testTradBase.SellAtMarket(code);

                    }
                }


                funds.Add(testTradBase.GetAllMyAsset());
            }
            if (isRecord) testTradBase.record += string.Format("{0} 总资产 {1}\n", stocks[stocks.Count - 1].Date, funds[funds.Count - 1]);
            Console.Write(testTradBase.record);
            return funds;
        }
        //计算波动范围
        private static List<Indicator> CalcRange(int n, double k1, double k2, List<Stock> stocks)
        {
            List<Indicator> dataList = new List<Indicator>();
            for (int i = 0; i < stocks.Count; i++)
            {
                var data = new Indicator
                {
                    Date = stocks[i].Date
                };
                if (i <= n)
                {
                    double range = Math.Max(stocks[i].HighPrice - stocks[i].ClosePrice, stocks[i].ClosePrice - stocks[i].LowPrice);
                    data.BollUp = stocks[i].OpenPrice + range * k1;
                    data.BollDown = stocks[i].OpenPrice - range * k2;
                    data.BollMd = stocks[i].OpenPrice;
                }
                else
                {
                    double range = 0;
                    for (int j = 0; j < n; j++)
                    {
                        var temp = Math.Max(stocks[i-j].HighPrice - stocks[i-j].ClosePrice, stocks[i-j].ClosePrice - stocks[i-j].LowPrice);
                        if (range < temp) range = temp;
                    }
                    data.BollUp = stocks[i].OpenPrice + range * k1;
                    data.BollMd = stocks[i].OpenPrice;
                    data.BollDown = stocks[i].OpenPrice - range * k2;
                }

                dataList.Add(data);
            }
            return dataList;
        }
    }
    #endregion

}
